﻿package  
{
	import Base.Sound.SoundManager;
	
	import Common.ActionManager;
	import Common.GameAction;
	import Common.GameDefine;
	import Common.GameFilters;
	import Common.GameLoading;
	import Common.RenderManager;
	
	import Events.LogicEvent;
	
	import battle.BattleData;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Point;
	import flash.text.TextField;
	
	import map.MapGrid;
	import map.MapPos;
	
	import ui.ChatUIHandler;
	import ui.MapUIHandler;
	import ui.PetInfoUIHandler;
	
	
	/**
	 * ...
	 * @author fox
	 */
	public class SceneManager
	{
		public var sceneSprite:Sprite = null;
		
		private var terrainBitmapData:BitmapData = null;
		private var bitmapData:BitmapData = null;
		private var bitmap:Bitmap = null;
		private var terrainBitmap:Bitmap = null;
		
		private var renderArray:Array = null;
		
		
		// render
		
		
		private var mapData:Object = null;
		
		private var actionBmpData:Object = null;
		
		private var mapBmpData:Object = null;
		private var mapInfoData:Object = null;
			
		private var pos:MapPos = null;
		private var lastPos:MapPos = null;
		private var point:Point = null;
		
		private var fight:Boolean = false;
		
		private var renderObject:Object = null;
		
		public var sceneX:int = 0;
		public var sceneY:int = 0;
		
		public var sceneHalfX:int = 0;
		public var sceneHalfY:int = 0;
		
		
		public function SceneManager() 
		{
		}
		
		
		public static var instance:SceneManager = null;
		public static function Instance():SceneManager
		{
			if ( instance == null )
			{
				instance = new SceneManager();
			}
			
			return instance;
		}
		
		
		public function release():void
		{
			sceneSprite = null;
		}
		
		
		public function update( delay:Number ):void
		{
			GameCreatureManager.instance.update( delay );
			GameUIManager.instance.update( delay );
						
			if ( fight ) 
			{
				BattleSession.instance.update( delay );
			}
		}
		
		
		public function render():void
		{
			if ( !RenderManager.redraw ) 
			{
				return;
			}
			
			bitmapData.lock();
			bitmapData.fillRect( bitmapData.rect , 0x00000000 );

			renderTerrain();
			
			if ( fight )
			{
				BattleSession.instance.render();
			}
			else
			{
				renderBuildingAndPlayer();
			}
			
//			if ( MapUIHandler.instance.isVisible )
//			{
//				
//			}
			
			bitmapData.unlock();

			RenderManager.redraw = false;
		}
		
				
		public function Fight( b:Boolean ):void
		{
			fight = b;
		}
		
		
		public function isFight():Boolean
		{
			return fight;
		}
		
		
		public function updateSize():void
		{
			RenderManager.redraw = true;
			
			if ( lastPos )
			{
				lastPos.mapGrid.setValue( GameDefine.INVALIDID , GameDefine.INVALIDID );
			}
			
			sceneX = RenderManager.instance.stageWidth / MapGrid.gridXHalf;
			sceneY = RenderManager.instance.stageHeight / MapGrid.gridYHalf;
			
			sceneX += 1;
			sceneY += 1;
			
			if( sceneX % 2 == 0 )
			{
				sceneX += 1;
			}
			
			sceneHalfX = sceneX / 2 + 1;
			
			if ( sceneY % 2 == 0 )
			{
				sceneY += 1;
			}
			
			if ( sceneX > sceneY )
			{
				sceneY = sceneX;
			}
			else
			{
				sceneX = sceneY;
			}
			
			sceneHalfX = sceneX / 2;
			sceneHalfY = sceneY / 2;
		}
		
		
		public var colorFilter:ColorMatrixFilter = null;
		public var filterArray:Array = null;
		
		public function resize():void
		{
			updateSize();
			
			if ( bitmap )
			{
				bitmapData.dispose();
				bitmapData = null;
				bitmapData = new BitmapData( RenderManager.instance.stageWidth , RenderManager.instance.stageHeight , true , 0xFFFFFFFF );
				
				terrainBitmapData.dispose();
				terrainBitmapData = null;
				terrainBitmapData = new BitmapData( RenderManager.instance.stageWidth , RenderManager.instance.stageHeight , false , 0xFFFFFFFF );
				
				terrainBitmap.bitmapData = null;
				terrainBitmap.bitmapData = terrainBitmapData;
				
				bitmap.bitmapData = null;
				bitmap.bitmapData = bitmapData;
				BattleSession.instance.setBitmapData( bitmapData );
				
				
				var array:Array = new Array( 1,0,0,0,-64,
					0,1,0,0,-64,
					0,0,1,0,-64,
					0,0,0,1,0 );
				colorFilter = new ColorMatrixFilter( array );
				filterArray = [ colorFilter ];
				sceneSprite.filters = filterArray;
			}
			
			BattleData.instance.resize();
		}
		
		
		public function init():void
		{
			updateSize();
			
			sceneSprite = new Sprite();
			RenderManager.instance.SceneSprite.addChild( sceneSprite );
			sceneSprite.filters = new Array();
			sceneSprite.filters.push( GameFilters.colorFilter );
			
			renderArray = new Array();
			
			sceneSprite.doubleClickEnabled = true;
			
			
			actionBmpData = ActionManager.instance.bmpData;
			
			mapBmpData = MapManager.instance.bmpData;
			mapInfoData = MapManager.instance.mapInfoData;
			
			point = new Point();
			lastPos = new MapPos(); lastPos.init();
			
			bitmapData = new BitmapData( RenderManager.instance.stageWidth , RenderManager.instance.stageHeight , true , 0xFFFFFFFF );
			terrainBitmapData = new BitmapData( RenderManager.instance.stageWidth , RenderManager.instance.stageHeight , false , 0xFFFFFFFF );
			
			terrainBitmap = new Bitmap( terrainBitmapData );
			bitmap = new Bitmap( bitmapData );
			
			renderObject = new Object();
			
			sceneSprite.addChild( terrainBitmap );
			sceneSprite.addChild( bitmap );
			
			BattleSession.instance.setBitmapData( bitmapData );
			sceneSprite.addEventListener( MouseEvent.CLICK , GameScene.instance.onMouseClick );
		}
		
		
		public function redraw():void
		{
			lastPos.init();
		}
		
		public function renderTerrain():void
		{
			if ( !MapManager.instance.isLoaded ) 
			{
				return;
			}
			
			pos = GameScene.instance.Pos;
			mapData = MapManager.instance.activeMapData;
			
			var draw:Boolean = true;
			if ( lastPos.mapGrid.equalsReal( pos.mapGrid ) && lastPos.mapID == pos.mapID )
			{
				draw = false;
			}
			else
			{
				lastPos.mapID = pos.mapID;
				lastPos.mapGrid.copy( pos.mapGrid );
			}
			
			if ( draw )
			{
				terrainBitmapData.lock();
				terrainBitmapData.fillRect( terrainBitmapData.rect , 0xFF000000 );
			}
			
			var renderIndex:int = -1;
			
			var renderObject:Object = new Object();
			
			for ( var i:int = 0; i < sceneY; i++ ) 
			{
				var renderLast:RenderObject = null;
				
				for ( var j:int = sceneX - 1; j >= 0; j-- ) 
				{
					if ( pos.mapGrid.x + j - sceneHalfX >= 0 && pos.mapGrid.x + j - sceneHalfX < mapData.x &&
					pos.mapGrid.y + i - sceneHalfY >= 0 && pos.mapGrid.y + i - sceneHalfY < mapData.y ) 
					{
						//real local pos
						var x:int = pos.mapGrid.x + j - sceneHalfX;
						var y:int = pos.mapGrid.y + i - sceneHalfY;
						
						var data:BitmapData = mapBmpData[ mapData.terrain[y][x].id ] ;
						
						if ( data )
						{
							if ( draw )
							{
								point.x = j * MapGrid.gridXHalf + i * MapGrid.gridXHalf;
								point.y = -j * MapGrid.gridYHalf + i * MapGrid.gridYHalf;
								
								point.x += mapInfoData[ mapData.terrain[y][x].id ].px;
								point.y += mapInfoData[ mapData.terrain[y][x].id ].py;
								
								point.x -= sceneX * MapGrid.gridXFour;
								point.y += sceneY * MapGrid.gridYFour;
								
								point.x -= pos.mapGrid.realPosX - ( pos.mapGrid.y * MapGrid.gridXHalf + pos.mapGrid.x * MapGrid.gridXHalf );
								point.y -= pos.mapGrid.realPosY + ( -pos.mapGrid.y * MapGrid.gridYHalf + pos.mapGrid.x * MapGrid.gridYHalf );
								
								if ( point.x + data.width > 0 && point.y + data.height > 0 &&
									point.x < RenderManager.instance.stageWidth && point.y < RenderManager.instance.stageHeight )
									terrainBitmapData.copyPixels( data , data.rect , point );
								
								data = null;
							}

						}
						else
						{
							MapManager.instance.loadTextureT( x , y );
						}
						
						if ( fight ) 
						{
							continue;
						}
						
						// render list
						
						var objectBuilding:RenderObject = mapData.building[y][x];
						
						if ( objectBuilding )
						{
							var id:int = objectBuilding.renderID;
							var index:int = objectBuilding.renderIndex;
							data = mapBmpData[ id ] ;
							
							if ( data && id > 55 && ( mapInfoData[ id ].f == 45 || mapInfoData[ id ].f == 1 ) && objectBuilding.renderE == 0 && objectBuilding.renderS == 0 ) 
							{
								if ( draw )
								{
									point.x = j * MapGrid.gridXHalf + i * MapGrid.gridXHalf ;
									point.y = -j * MapGrid.gridYHalf + i * MapGrid.gridYHalf;
										
									point.x += mapInfoData[ id ].px;
									point.y += mapInfoData[ id ].py;
									
									point.x -= sceneX * MapGrid.gridXFour;
									point.y += sceneY * MapGrid.gridYFour;
									
									point.x -= pos.mapGrid.realPosX - ( pos.mapGrid.y * MapGrid.gridXHalf + pos.mapGrid.x * MapGrid.gridXHalf );
									point.y -= pos.mapGrid.realPosY + ( -pos.mapGrid.y * MapGrid.gridYHalf + pos.mapGrid.x * MapGrid.gridYHalf );
									
									if ( point.x + data.width > 0 && point.y + data.height > 0 &&
										point.x < RenderManager.instance.stageWidth && point.y < RenderManager.instance.stageHeight )
									terrainBitmapData.copyPixels( data , data.rect , point );
								}
								
							}
							else if ( id > 55 && ( mapInfoData[ id ].f != 45 && mapInfoData[ id ].f != 1 ) ) 
							{
								var renderBuilding:RenderObject = renderObject[ index ];
								if ( renderBuilding ) 
								{
									if ( renderLast )
									{
										if ( renderLast == renderBuilding ) 
										{
											//continue;
										}
										else
										{
											var parent:RenderObject = renderLast.renderParent;
											var b:Boolean = false;

											while ( parent )
											{
												if ( parent == renderBuilding )
												{
													b = true;
													break;
												}
												
												parent = parent.renderParent;
											}
											
											parent = null;
											
											if ( !b )
											{
												renderLast.addChild( renderBuilding );
											}
										}
										
									}
									
									renderLast = renderBuilding;
								}
								else
								{
									objectBuilding.renderJ = j - objectBuilding.renderE;
									objectBuilding.renderI = i + objectBuilding.renderS;
									
									renderObject[ index ] = objectBuilding;
									
									if ( !renderLast )
									{
										renderArray.push( objectBuilding );
									}
									
									if ( renderLast )
									{
										renderLast.addChild( objectBuilding );
									}
									
									renderLast = objectBuilding;
								}
								
								data = null;
								renderBuilding = null;
							}
							
						}
						
						var objectCreature:Object = GameCreatureManager.instance.getPlayerScene( x , y );
						
						if ( objectCreature )
						{
							var renderPlayer:RenderObject = new RenderObject();
							renderPlayer.renderJ = j;
							renderPlayer.renderI = i;
							renderPlayer.renderIndex = renderIndex;
							renderIndex--;
							renderPlayer.renderObject = objectCreature;
							
							if ( !renderLast )
							{
								renderArray.push( renderPlayer );
							}
							
							if ( renderLast ) 
							{
								renderLast.addChild( renderPlayer );
							}
							
							renderLast = renderPlayer;
							renderPlayer = null;
						}
						
						
						objectCreature = GameCreatureManager.instance.getNpcScene( x , y );
						
						if ( objectCreature )
						{
							var renderNpc:RenderObject = new RenderObject();
							renderNpc.renderJ = j;
							renderNpc.renderI = i;
							renderNpc.renderIndex = renderIndex;
							renderIndex--;
							renderNpc.renderObject = objectCreature;
							
							if ( !renderLast )
							{
								renderArray.push( renderNpc );
							}
							
							if ( renderLast )
							{
								renderLast.addChild( renderNpc );
							}
							
							renderLast = renderNpc;
							renderNpc = null;
						}
					}
					
				}
				
			}
			
			if ( draw )
			{
				terrainBitmapData.unlock();
			}
			
			for ( var obj:Object in renderObject )
			{
				delete renderObject[obj];
			}
		}
		
		
		public function renderBuildingAndPlayer():void
		{
			if ( !MapManager.instance.isLoaded )
			{
				return;
			}
			
			while ( renderArray.length )
			{
				var item:RenderObject = renderArray[0];
				
				if ( !item.renderParent )
				{
					renderDisplayObj( item );
					
					item.clear();
				}
				
				renderArray.shift();
			}
			
		}
		
		
		private function renderDisplayObj( obj:RenderObject ):void
		{
			if ( !obj.renderObject )
			{
				// building
				
				var id:int = obj.renderID;
				var data:BitmapData = mapBmpData[ id ];
				
				if ( data ) 
				{
					point.x = obj.renderJ * MapGrid.gridXHalf + obj.renderI * MapGrid.gridXHalf ;
					point.y = -obj.renderJ * MapGrid.gridYHalf + obj.renderI * MapGrid.gridYHalf;
					
					point.x += mapInfoData[ id ].px;
					point.y += mapInfoData[ id ].py;
					
					point.x -= sceneX * MapGrid.gridX * 0.25;
					point.y += sceneY * MapGrid.gridY * 0.25;
					
					point.x -= pos.mapGrid.realPosX - ( pos.mapGrid.y * MapGrid.gridXHalf + pos.mapGrid.x * MapGrid.gridXHalf );
					point.y -= pos.mapGrid.realPosY + ( -pos.mapGrid.y * MapGrid.gridYHalf + pos.mapGrid.x * MapGrid.gridYHalf );
					
					if ( point.x + data.width > 0 && point.y + data.height > 0 &&
						point.x < RenderManager.instance.stageWidth && point.y < RenderManager.instance.stageHeight )
					bitmapData.copyPixels( data , data.rect , point , null , null , true );
					
					data = null;
				}
				else
				{
					MapManager.instance.loadTextureB( id );
				}
				
			}
			else
			{
				// player
				
				for ( var key:String in obj.renderObject ) 
				{
					var item:GameCreature = obj.renderObject[ key ] as GameCreature;
					
					if ( !item ) 
					{
						continue;
					}
					
					var grid:MapGrid = item.MMapGrid;
					
					var textureID:int = item.ActionTextureID;
					
					if ( !actionBmpData[ textureID ] ) 
					{
						continue;
					}
					
					//if ( textureID != GameDefine.INVALIDID ) 
					//{
						point.x = obj.renderJ * MapGrid.gridXHalf + obj.renderI * MapGrid.gridXHalf;
						point.y = -obj.renderJ * MapGrid.gridYHalf + obj.renderI * MapGrid.gridYHalf;
						
						point.x += actionBmpData[ textureID ].px;
						point.y += actionBmpData[ textureID ].py;
						
						point.x -= sceneX * MapGrid.gridX * 0.25;
						point.y += sceneY * MapGrid.gridY * 0.25;
						
						point.x -= pos.mapGrid.realPosX - ( pos.mapGrid.y * MapGrid.gridXHalf + pos.mapGrid.x * MapGrid.gridXHalf );
						point.y -= pos.mapGrid.realPosY + ( -pos.mapGrid.y * MapGrid.gridYHalf + pos.mapGrid.x * MapGrid.gridYHalf );
						
						point.x += grid.realPosX - ( grid.y * MapGrid.gridXHalf + grid.x * MapGrid.gridXHalf );
						point.y += grid.realPosY + ( -grid.y * MapGrid.gridYHalf + grid.x * MapGrid.gridYHalf );
						
						if ( point.x + actionBmpData[ textureID ].w > 0 && point.y + actionBmpData[ textureID ].h > 0 &&
							point.x < RenderManager.instance.stageWidth && point.y < RenderManager.instance.stageHeight )
						bitmapData.copyPixels( actionBmpData[ textureID ].bd , actionBmpData[ textureID ].bd.rect , point , null , null , true );
						
						if ( item.team && item.team.leader == item )
						{
							var textureID1:int = item.CommomActionTextureID( GameAction.TEAMLEADER );
							
							if ( textureID1 != GameDefine.INVALIDID )
							{
								if ( actionBmpData[ textureID1 ]  )
								{
									point.x -= actionBmpData[ textureID ].px;
									point.y -= actionBmpData[ textureID ].py;
									
									point.x += actionBmpData[ textureID1 ].px;
									point.y += actionBmpData[ textureID1 ].py;
									
									point.y -= actionBmpData[ textureID ].h;
									
									bitmapData.copyPixels( actionBmpData[ textureID1 ].bd , actionBmpData[ textureID1 ].bd.rect , point , null , null , true );
								}
							}
						}
						
					//}
					
					item = null;
					grid = null;
				}
			}
			
			
			for each ( var o:RenderObject in obj.renderChildrenArray ) 
			{
				renderDisplayObj( o );
			}
			
		}
		
		
		private function onSceneClick( e:MouseEvent ):void
		{
			
		}
		
		
		
		
		
		
		
	}
	
}
